package ffte.evaluate.vectors

import breeze.math.Complex

/**
 * Complex number utilities for test vector generation
 *
 * This object provides utility functions for working with fixed-point
 * complex numbers in test vector generation and validation.
 */
object Cplx {

    /** Implicit conversion from Cplx to Breeze Complex */
    implicit def cplxi2Complex(x : Cplx) : Complex = Complex(x.re,x.im)

    /** Integer absolute value function */
    def iabs(a:Int) = if(a<0) -a else a
}

/**
 * Fixed-point complex number for test vectors
 *
 * This class represents a complex number with integer components
 * suitable for fixed-point testing and validation.
 *
 * @param re Real component (integer)
 * @param im Imaginary component (integer)
 */
case class Cplx(re:Int,im:Int) {

    /** Complex subtraction */
    def -(that:Cplx) = Cplx(this.re-that.re,this.im-that.im)

    /** L1 norm (Manhattan distance) for error calculations */
    def norm1 : Int= Cplx.iabs(re)+Cplx.iabs(im)
}

/**
 * Test vector container for FFT validation
 *
 * This case class holds input and expected output vectors for
 * FFT algorithm testing and validation.
 *
 * @param d Input data vector (complex integers)
 * @param q Expected output vector (complex integers)
 */
case class TestVectors(d:Array[Cplx],q:Array[Cplx])

/**
 * Test vector generation trait
 *
 * This trait defines the interface for generating test vectors
 * for FFT algorithm validation. It supports various test patterns
 * including impulses, noise, and specific frequency components.
 *
 * @tparam N Transform size
 * @tparam S Scaling factor
 */
trait genVector {

    /** Transform size */
    val N : Int

    /** Scaling factor */
    val S : Int

    /** Generate test vectors with specified scaling */
    def TV(sx:Int) : TestVectors

    /** Generate noise test vectors */
    def NV(k:Int,s:Int)  : TestVectors

    /** Generate impulse test vectors */
    def IV(k:Int,s:Int)  : TestVectors

    /** Counter for incrementing test patterns */
    var inc = 0

    /**
     * Generate test vectors based on pattern type
     *
     * Supports various test patterns:
     * - K = 0: Standard test vectors
     * - K = N: Noise vectors
     * - K = -N: Incrementing impulse vectors
     * - K < 0: Impulse at position |K|
     * - K > 0: Noise with seed K
     *
     * @param K Pattern type/seed
     * @param dW Data width for scaling calculations
     * @return Generated test vectors
     */
    def test_vectors(K:Int,dW:Int) = K match {
        case 0              => TV(dW-3)
        case k if(k == -N)  => { inc += 1; IV(inc%N,dW-3)}
        case N              => NV(0,dW-3)
        case k if(k<0)      => IV((-k)%N,dW-3)
        case _              => NV(K%N,dW-3)
    }
}

/**
 * Test vector utility functions
 *
 * This object provides conversion utilities for transforming between
 * floating-point and fixed-point representations in test vector
 * generation and validation.
 */
object TestVectors {

    /**
     * Convert double to fixed-point integer
     *
     * Converts a floating-point double to a fixed-point integer
     * representation using the specified scaling factor.
     *
     * @param x Input double value
     * @param s Scaling factor (fractional bits)
     * @return Fixed-point integer representation
     */
    def d2i(x: Double, s :Int) = {
        Math.round(x*Math.pow(2,s)).toInt
    }

    /**
     * Convert complex double to fixed-point complex integer
     *
     * Converts a complex number with double components to the
     * Cplx fixed-point representation.
     *
     * @param x Input complex double
     * @param s Scaling factor (fractional bits)
     * @return Fixed-point complex integer
     */
    def c2ci(x:Complex,s:Int) = Cplx(d2i(x.re,s),d2i(x.im,s))

    /**
     * Convert array of complex doubles to fixed-point complex integers
     *
     * Applies c2ci conversion to an entire array of complex numbers.
     *
     * @param x Array of input complex doubles
     * @param s Scaling factor (fractional bits)
     * @return Array of fixed-point complex integers
     */
    def fromVC(x: Array[Complex], s:Int) = x.map(c2ci(_,s))
}
    
